﻿using System;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using advadev.CanOpen;


namespace advadev.CanOpen.UnitTests
{

    /// <summary>
    /// Represents the network management boot-up message write transfer
    /// unit tests
    /// </summary>
    [TestClass]
    public class NetworkManagementBootUpMessageWriteTransferTest : ICanOpenObjectDictionaryContainer
    {

        #region constructor tests
        /// <summary>
        /// Constructor test
        /// </summary>
        [TestMethod]
        public void ConstructorTest()
        {
            // initialization
            NetworkManagementBootUpMessageWriteTransfer testObject = null;

            // node id out of range parameter
            try
            {
                testObject = new NetworkManagementBootUpMessageWriteTransfer(0);
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException)
            {
            }
            catch
            {
                Assert.Fail();
            }
            try
            {
                testObject = new NetworkManagementBootUpMessageWriteTransfer(128);
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException)
            {
            }
            catch
            {
                Assert.Fail();
            }
        }
        #endregion constructor tests


        #region producer side tests
        /// <summary>
        /// Producer side test
        /// </summary>
        [TestMethod]
        public void ProducerSideTest()
        {
            // initialization
            byte nodeId = 103;
            UInt16 cobId = 0x100;
            NetworkManagementBootUpMessageWriteTransfer testObject = null;

            // test with default COB-ID
            testObject = new NetworkManagementBootUpMessageWriteTransfer(nodeId);
            testObject.Start();
            Assert.AreEqual(false, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(1, testObject.PendingSendMessages.Count);
            Assert.AreEqual(0x767, testObject.PendingSendMessages[0].CanId);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte0);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte1);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte2);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte3);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte4);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte5);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte6);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte7);
            Assert.AreEqual((uint)0, testObject.PendingSendMessages[0].Length);
            testObject.ContinueAfterSendingMessages();
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);

            // test with changed COB-ID
            testObject = new NetworkManagementBootUpMessageWriteTransfer(nodeId, cobId);
            testObject.Start();
            Assert.AreEqual(false, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(1, testObject.PendingSendMessages.Count);
            Assert.AreEqual(cobId + nodeId, testObject.PendingSendMessages[0].CanId);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte0);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte1);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte2);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte3);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte4);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte5);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte6);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte7);
            Assert.AreEqual((uint)0, testObject.PendingSendMessages[0].Length);
            testObject.ContinueAfterSendingMessages();
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);
        }
        #endregion producer side tests


        #region is network management boot-up message write transfer request tests
        /// <summary>
        /// Is network management boot-up message write transfer request
        /// test
        /// </summary>
        [TestMethod]
        public void IsNetworkManagementBootUpMessageWriteTransferRequestTest()
        {
            // initialization
            bool isNetworkManagementBootUpMessageWriteTransferRequest = false;
            byte nodeId = 0;
            NetworkManagementBootUpMessageReceivedEventHandler handler = new NetworkManagementBootUpMessageReceivedEventHandler((object sender, NetworkManagementBootUpMessageReceivedEventArgs args) =>
            {
                nodeId = args.NodeId;
            });
            NetworkManagementBootUpMessageWriteTransfer testObject = null;

            // test with valid received can open message
            nodeId = 0;
            isNetworkManagementBootUpMessageWriteTransferRequest = NetworkManagementBootUpMessageWriteTransfer.IsNetworkManagementBootUpMessageWriteTransfer(new CanOpenMessage(0x767, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), out testObject, handler);
            Assert.AreEqual(true, isNetworkManagementBootUpMessageWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.IsTrue(testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.AreEqual(103, nodeId);

            // test with wrong COB-ID
            isNetworkManagementBootUpMessageWriteTransferRequest = NetworkManagementBootUpMessageWriteTransfer.IsNetworkManagementBootUpMessageWriteTransfer(new CanOpenMessage(0x167, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), out testObject, handler);
            Assert.AreNotEqual(true, isNetworkManagementBootUpMessageWriteTransferRequest);
            Assert.IsNull(testObject);

            // test with handler is null
            nodeId = 0;
            isNetworkManagementBootUpMessageWriteTransferRequest = NetworkManagementBootUpMessageWriteTransfer.IsNetworkManagementBootUpMessageWriteTransfer(new CanOpenMessage(0x767, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), out testObject, null);
            Assert.AreEqual(true, isNetworkManagementBootUpMessageWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.IsTrue(testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.AreEqual(0, nodeId);
        }
        #endregion is network management boot-up message write transfer request tests


        #region consumer side tests
        /// <summary>
        /// Consumer side test
        /// </summary>
        [TestMethod]
        public void ConsumerSideTest()
        {
            // initialization
            bool isNetworkManagementBootUpMessageWriteTransferRequest = false;
            byte nodeId = 103;
            UInt16 cobId = 0x100;
            bool handlerCalled = false;
            NetworkManagementBootUpMessageReceivedEventHandler handler = new NetworkManagementBootUpMessageReceivedEventHandler((object sender, NetworkManagementBootUpMessageReceivedEventArgs args) =>
            {
                handlerCalled = true;
            });
            NetworkManagementBootUpMessageWriteTransfer testObject = null;
            NetworkManagementBootUpMessageWriteTransfer producerTransfer = null;

            // test with default COB-ID
            handlerCalled = false;
            producerTransfer = new NetworkManagementBootUpMessageWriteTransfer(nodeId);
            producerTransfer.Start();
            isNetworkManagementBootUpMessageWriteTransferRequest = NetworkManagementBootUpMessageWriteTransfer.IsNetworkManagementBootUpMessageWriteTransfer(producerTransfer.PendingSendMessages[0], out testObject, handler);
            Assert.AreEqual(true, isNetworkManagementBootUpMessageWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.AreEqual(true, handlerCalled);
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);

            // test with changed COB-ID
            handlerCalled = false;
            producerTransfer = new NetworkManagementBootUpMessageWriteTransfer(nodeId, cobId);
            producerTransfer.Start();
            isNetworkManagementBootUpMessageWriteTransferRequest = NetworkManagementBootUpMessageWriteTransfer.IsNetworkManagementBootUpMessageWriteTransfer(producerTransfer.PendingSendMessages[0], out testObject, cobId, handler);
            Assert.AreEqual(true, isNetworkManagementBootUpMessageWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.AreEqual(true, handlerCalled);
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);

            // test without handler
            handlerCalled = false;
            producerTransfer = new NetworkManagementBootUpMessageWriteTransfer(nodeId);
            producerTransfer.Start();
            isNetworkManagementBootUpMessageWriteTransferRequest = NetworkManagementBootUpMessageWriteTransfer.IsNetworkManagementBootUpMessageWriteTransfer(producerTransfer.PendingSendMessages[0], out testObject, null);
            Assert.AreEqual(true, isNetworkManagementBootUpMessageWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.AreEqual(false, handlerCalled);
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);
        }
        #endregion consumer side tests


        #region ICanOpenObjectDictionaryContainer
        /// <summary>
        /// Gets the node id of the can open object dictionary container
        /// </summary>
        byte ICanOpenObjectDictionaryContainer.NodeId
        {
            get
            {
                return 103;
            }
        }

        /// <summary>
        /// Gets the can open object with the given index as can open data field
        /// object
        /// </summary>
        /// <param name="index">
        /// Index of the can open object to get
        /// </param>
        /// <returns>
        /// The can open object with the given index as data field object or
        /// null
        /// </returns>
        ICanOpenDataFieldObject ICanOpenObjectDictionaryContainer.GetCanOpenObject(UInt16 index)
        {
            return null;
        }

        /// <summary>
        /// Gets the can open object with the given index and sub index as can
        /// open value object
        /// </summary>
        /// <param name="index">
        /// Index of the can open object to get
        /// </param>
        /// <param name="subIndex">
        /// Sub index of the can open object to get
        /// </param>
        /// <returns>
        /// The can open object with the given index and sub index as value
        /// object or null
        /// </returns>
        ICanOpenValueObject ICanOpenObjectDictionaryContainer.GetCanOpenObject(UInt16 index, byte subIndex)
        {
            return null;
        }
        #endregion ICanOpenObjectDictionaryContainer

    }

}
